<?php
// +----------------------------------------------------------------------
// | INPHP
// | Copyright (c) 2023 https://inphp.cc All rights reserved.
// | Author: 幺月儿(https://gitee.com/lulanyin) Email: inphp@qq.com
// | 该文件的开源协议以所在项目的LICENSE文件为准，请遵守开源协议要求
// +----------------------------------------------------------------------
// | 提现
// +----------------------------------------------------------------------
namespace app\finance\http\api;

use app\admin\attributes\auth;
use app\finance\model\BalanceModel;
use app\finance\model\CashierModel;
use app\finance\model\CheckoutModel;
use app\sso\model\UserModel;
use Inphp\Core\Db\Db;
use Inphp\Core\Db\PDO\Query;
use Inphp\Core\Modules;
use Inphp\Core\Object\Message;
use Inphp\Core\Util\Str;

#[auth] class checkout
{
    /**
     * 账户UID
     * @var int
     */
    public int $uid = 0;

    /**
     * 账户数据
     * @var array
     */
    public array $user = [];

    /**
     * 获取指定提现订单
     * 非管理员仅可获取自己的
     * @return Message
     */
    public function index(): Message
    {

    }

    /**
     * 列表
     * 非管理员仅可获取自己的
     * @param array|null $params
     * @return array
     */
    public function list(?array $params = null): array
    {
        $params = $params ?? getClient()->get;
        $admin = $params["admin"] ?? 0;
        $admin = $admin == 1 ? 1 : 0;
        $sso = Modules::getModule("sso");
        //判断是不是管理员
        $admin = $admin == 1 && ($this->user["admin"] == 1 || ($sso && !empty($this->user["groups"]) && \app\sso\model\UserModel::matchPermission(["finance/checkout/list"], $this->user["groups"])));
        $db = CheckoutModel::emptyQuery("c")
            ->select([
                "c.*"
            ]);
        //可搜索
        $keyword = $params["keyword"];
        $keyword = !empty($keyword) ? Str::trim($keyword) : null;
        if ($admin && $sso) {
            $db->join(UserModel::tableName()." u", "c.uid=u.uid")
                ->addSelect([
                    "u.nickname, u.username"
                ]);
            if (!empty($keyword)) {
                if (is_numeric($keyword) && strlen($keyword) < 12) {
                    //数字，查询手机号码
                    $db->where(function(Query $q) use($keyword) {
                        $q->whereLike("u.phone", $keyword)
                            ->orWhereLike("c.orderId", $keyword);
                    });
                } else {
                    //其它，查询昵称
                    $db->where(function(Query $q) use($keyword) {
                        $q->whereLike("u.username", $keyword)
                            ->orWhereLike("from_base64(substr(u.nickname, 23))", $keyword);
                    });
                }
            }
        }
        if (!$admin) {
            $db->where("b.uid", $this->uid);
        }
        if (((!$sso && $admin) || !$admin ) && !empty($keyword)) {
            $db->whereLike("c.orderId", $keyword);
        }
        //行数
        $rows = $db->rows();
        //当前页数
        $page = $params['page'] ?? 1;
        $page = is_numeric($page) && $page > 0 ? ceil($page) : 1;
        //总页数
        $pages = 1;
        //列表数据
        $list = [];
        if ($rows > 0) {
            $total = $params["total"] ?? 30;
            $total = is_numeric($total) && $total > 2 ? $total : 30;
            $pages = ceil($rows / $total);
            $page = $page > $pages ? $pages : $page;
            $offset = $total * ($page - 1);
            //可排序
            $balanceNames = BalanceModel::names();
            $obfList = ["quantity", "amount", "time"];
            $obf = $params["obf"] ?? "time";
            $obf = in_array($obf, $obfList) ? $obf : "time";
            $obt = $params["obt"] ?? "asc";
            $obt = $obt == "asc" ? "asc" : "desc";
            $db->orderBy("c.{$obf}", $obt);
            $list = $db->get($total, $offset);
            foreach ($list as &$item) {
                if ($admin && $sso) {
                    $item['nickname'] = \app\sso\model\UserModel::decodeNickname($item['nickname']);
                }
                $item["balanceName"] = $balanceNames[$item["balance"]] ?? "未知";
            }
        }
        //返回列表数据，包含行数、页码、总页数、数据列表
        return compact("rows", "page", "pages", "list");
    }

    /**
     * 申请提现
     * @return Message
     */
    public function request(): Message
    {
        if ($this->uid <= 0) {
            return httpMessage("无权限");
        }
        $balanceNames = BalanceModel::names();
        //资产
        $balance = POST("balance");
        $balance = !empty($balance) ? Str::trim($balance) : null;
        if (empty($balance)) {
            return httpMessage("缺少资产类型");
        }
        if (!in_array($balance, array_keys($balanceNames))) {
            return httpMessage("资产无效");
        }
        //数额
        $quantity = POST("quantity");
        $quantity = is_numeric($quantity) && $quantity > 0 ? round($quantity, 2) : 0;
        if ($quantity <= 0) {
            return httpMessage("提现数额无效");
        }
        //需要输入二级密码
        $sso = Modules::getModule("sso");
        if (!$sso) {
            return httpMessage("缺少SSO模块");
        }
        $sp = POST("sp");
        if (empty($sp)) {
            return httpMessage("缺少安全操作密码");
        }
        if (!\app\sso\model\UserModel::verifySafePassword($sp, $this->uid)) {
            return httpMessage("安全操作密码错误");
        }
        //
        $myBalance = BalanceModel::getBalance($this->uid);
        $max = $myBalance[$balance] ?? 0;
        if ($max < $quantity) {
            return httpMessage("余额不足，剩余：{$max}");
        }
        //配置
        $config = getFinanceConfig("checkout");
        if (!isset($config["balance"][$balance])) {
            return httpMessage("该资产不可提现");
        }
        $config = $config["balance"][$balance];
        //最小提现金额
        $min = $config["min"] ?? 0;
        $min = is_numeric($min) && $min > 0 ? $min : 0;
        if ($quantity < $min) {
            return httpMessage("最小提现数额为：{$min}");
        }
        //最大提现金额
        $max = $config["max"] ?? 0;
        $max = is_numeric($max) && $max > 0 ? $max : 0;
        if ($quantity > $min) {
            return httpMessage("最大提现数额为：{$max}");
        }
        //手续费
        $fee = $config["fee"] ?? 0;
        $fee = is_numeric($fee) && $fee > 0 ? round($fee, 2) : 0;
        $feeTo = $config["feeTo"] ?? null;
        $feeTo = in_array($feeTo, array_keys($balanceNames)) ? $feeTo : null;
        $feeToRatio = $config["feeToRatio"] ?? 0;
        $feeToRatio = is_numeric($feeToRatio) && $feeToRatio > 0 ? round($feeToRatio, 2) : 0;

        //计算
        $currency = CashierModel::currency();
        $currencyRatio = $config["ratio"] ?? 0;
        $currencyRatio = is_numeric($currencyRatio) && $currencyRatio > 0 ? round($currencyRatio, 2) : 0;
        if ($currencyRatio <= 0) {
            return httpMessage("由于提现汇率为0，无法进行提现！");
        }
        //总金额
        $amount = bcmul($quantity, $currencyRatio, 2);
        if ($amount <= 0) {
            return httpMessage("由于提现金额为0，无法进行提现！");
        }
        $fee = $fee >= 1 ? $fee : bcmul($fee, $quantity, 2);
        if ($fee >= $quantity) {
            return httpMessage("由于手续费设置超限，无法进行提现");
        }
        //手续费
        $feeAmount = bcmul($fee, $currencyRatio, 2);
        $getAmount = bcsub($amount, $feeAmount, 2);
        //
        $data = [
            "orderId"       => makeOrderId(),
            "uid"           => $this->uid,
            "balance"       => $balance,
            "quantity"      => $quantity,
            "currency"      => $currency,
            "currencyRatio" => $currencyRatio,
            "fee"           => $fee,
            "amount"        => $amount,
            "feeTo"         => $feeTo,
            "feeToRatio"    => $feeTo ? $feeToRatio : 0,
            "feeAmount"     => $feeAmount,
            "getAmount"     => $getAmount,
            //2023.10.6 暂不实现提现收款账户关联，仅实现提现功能的流程
            "bank"          => "支付宝",
            "name"          => "暂不关联",
            "account"       => "13888888888",
            "state"         => 2
        ];
        Db::begin();
        $db = CheckoutModel::emptyQuery();
        if ($db->insert($data)) {
            if (CashierModel::pay($this->uid, $data["orderId"], "finance_checkout", $data["quantity"], $data["balance"], $this->uid)) {
                Db::commit();
                return httpMessage(0, "操作成功，请等待审核");
            }
        }
        Db::rollback();
        return httpMessage("订单处理失败");
    }

    /**
     * 管理员对申请单进行确认
     * 涉及提现，可能有即时到账的需求
     * @return Message
     */
    public function confirm(): Message
    {
        //订单号
        $orderId = POST("orderId");
        $orderId = is_numeric($orderId) && $orderId > 0 ? $orderId : 0;
        if ($orderId <= 0) {
            return httpMessage("订单号无效");
        }
        //处理结果
        $state = POST("state");
        $state = $state == 1 || $state == '0' ? $state : null;
        if (is_null($state)) {
            return httpMessage("结果状态未知，无法处理");
        }
        //说明
        $bak = POST("bak");
        $bak = !empty($bak) ? trim($bak) : null;
        //
        $sso = Modules::getModule("sso");
        //判断是不是管理员
        $admin = $this->user["admin"] == 1 || ($sso && !empty($this->user["groups"]) && \app\sso\model\UserModel::matchPermission(["finance/checkout/confirm"], $this->user["groups"]));
        if (!$admin) {
            return httpMessage(31);
        }
        //开始处理
        $order = CheckoutModel::getRowByPrimaryKey($orderId);
        if (empty($order)) {
            return httpMessage("订单号无效");
        }
        if ($order["state"] != 2 || $order["state"] != 3) {
            return httpMessage("该订单已处理，不可重复操作");
        }
    }
}